﻿using System;
using System.Text;
using System.Web;
using System.Data;
using System.Xml;
using System.Reflection;
using System.Collections;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using YiYiTong.Rocket.Helper;
using System.Collections.Generic;

namespace YiYiTong.Rocket.Helper
{
    public class Utils
    {
        public static long GetUnixStamp(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
            long t = (time.Ticks - startTime.Ticks) / 10000;            //除10000调整为13位
            return t;
        }

        public static string ModifyMobile(string mobile)
        {
            if(!string.IsNullOrWhiteSpace( mobile) && mobile.Length >= 11)
            {
                return mobile.Substring(0, 3) + "****" + mobile.Substring(7);
            }
            return mobile;
        }
        /// <summary>
        /// 四舍五入,默认保留2位小数
        /// </summary>
        /// <param name="num"></param>
        /// <param name="digit">保留位数</param>
        /// <returns></returns>
        public static decimal MathRound(decimal num, int digit = 0)
        {
            if (digit <= 0)
                digit = 2;
            return Math.Round(num, digit, MidpointRounding.AwayFromZero);
        }

        /// <summary>
        /// 比较间隔时间是否大于n个月
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static bool CompareDate(string begdate, string enddate, int n)
        {
            DateTime dtBegDate = Convert.ToDateTime(begdate);
            DateTime dtEndDate = Convert.ToDateTime(enddate);
            dtBegDate = dtBegDate.AddMonths(n);
            if (dtBegDate < dtEndDate)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 验证身份证号
        /// </summary>
        /// <param name="cardno"></param>
        /// <returns></returns>
        public static bool CheckIDNumber(string cardno)
        {
            string str = @"^\d+$";
            Regex reg = new Regex(str);

            //身份证在10-18位
            if (cardno.Length > 10 && cardno.Length <= 18)
            {
                //截取字符串
                string subCardNo = cardno.Substring(0, cardno.Length - 1);
                //身份证全部是数字或最后一位是X
                if (reg.IsMatch(cardno) || (reg.IsMatch(subCardNo) && cardno.ToUpper().EndsWith("X")))
                    return true;
                else
                    return false;
            }
            else
                return false;
        }

        /// <summary>
        /// 日期判断
        /// </summary>
        /// <param name="strDate"></param>
        /// <returns></returns>
        public static bool IsDate(string strDate)
        {
            try
            {
                DateTime.Parse(strDate);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 实体类转xml字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static string ToXml<T>(T t) where T : class
        {
            StringBuilder sb = new StringBuilder("<xml>");
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                string name = propertyInfo.Name;
                string value = propertyInfo.GetValue(t, null).ToString();
                if (!string.IsNullOrEmpty(value))
                    sb.Append("<").Append(name).Append(">").Append(value).Append("</").Append(name).Append(">");
            }

            return sb.Append("</xml>").ToString();
        }

        /// <summary>
        /// 实体类转xml字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static string ToCDATAXml<T>(T t) where T : class
        {
            StringBuilder sb = new StringBuilder("<xml>");
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                string name = propertyInfo.Name;
                string value = propertyInfo.GetValue(t, null).ToString();
                if (!string.IsNullOrEmpty(value))
                    sb.Append("<").Append(name).Append("><![CDATA[").Append(value).Append("]]></").Append(name).Append(">");
            }

            return sb.Append("</xml>").ToString();
        }

        /// <summary>
        /// Hashtable转xml字符串
        /// </summary>
        /// <param name="ht"></param>
        /// <returns></returns>
        public static string ToXml(Hashtable ht)
        {
            StringBuilder sb = new StringBuilder("<xml>");
            foreach (DictionaryEntry de in ht)
            {
                string key = de.Key.ToString();
                sb.Append("<").Append(key).Append(">").Append(de.Value.ToString()).Append("</").Append(key).Append(">");
            }

            return sb.Append("</xml>").ToString();
        }


        /// <summary>
        /// xml字符串转xml
        /// </summary>
        public static Hashtable StrToXml(string content)
        {
            Hashtable hat = new Hashtable();
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(content);
                XmlNode root = xmlDoc.SelectSingleNode("xml");
                XmlNodeList xnl = root.ChildNodes;

                foreach (XmlNode xnf in xnl)
                {
                    SetHashtable(hat, xnf.Name, xnf.InnerText);
                }
            }
            catch (Exception e) { }
            return hat;
        }


        /// <summary>
        /// xml字符串转xml
        /// </summary>
        public static Hashtable StrToXml(string content, string node = "xml")
        {
            Hashtable hat = new Hashtable();
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(content);
                XmlNode root = xmlDoc.SelectSingleNode(node);
                XmlNodeList xnl = root.ChildNodes;

                foreach (XmlNode xnf in xnl)
                {
                    SetHashtable(hat, xnf.Name, xnf.InnerText);
                }
            }
            catch (Exception e) { }
            return hat;
        }

        /// <summary>
        /// 设置hashtable值
        /// </summary>
        public static Hashtable SetHashtable(Hashtable hat, string name, string value)
        {
            if (name != null && name != "")
            {
                if (hat.Contains(name))
                {
                    hat.Remove(name);
                }

                hat.Add(name, value);
            }
            return hat;
        }

        /// <summary>
        /// 获取hashtable值
        /// </summary>
        public static string GetHtValue(Hashtable hat, string name)
        {
            string s = (string)hat[name];
            return (null == s) ? "" : s;
        }


        /// <summary>
        /// 验证手机号
        /// </summary>
        /// <param name="mobile">手机号</param>
        /// <returns></returns>
        public static bool CheckMobile(string mobile)
        {
            string str = @"^\d+$";
            Regex reg = new Regex(str);

            //手机号全是数字并以1开头
            if (reg.IsMatch(mobile) && mobile.StartsWith("1") && mobile.Length == 11)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 检查手机验证码
        /// </summary>
        public static bool CheckMobileCode(string vercode)
        {
            bool flag = true;
            if (vercode.Length == 6)
                flag = CheckNumber(vercode);
            else
                flag = false;
            return flag;
        }

        /// <summary>
        /// 判断是否是数字
        /// </summary>
        /// <returns></returns>
        public static bool CheckNumber(string strValue)
        {
            bool flag = true;
            //验证数字
            char[] code = strValue.ToCharArray();
            for (int i = 0; i < code.Length; i++)
            {
                if (!Char.IsNumber(code[i]))
                {
                    flag = false;
                    break;
                }
            }
            return flag;
        }

        public static string GetRandom()
        {
            //生成6位随机数
            Random rand = new Random(Guid.NewGuid().GetHashCode());
            string iRand = rand.Next(100000, 999999).ToString();
            return iRand;
        }

        /// <summary>
        /// 生成个人会员6位随机密码例如：Abc123
        /// </summary>
        /// <returns></returns>
        public static string GetRandomPwd(int n)
        {
            string strRandomPwd = string.Empty;
            string[] strCapital = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "L", "R", "P", "Q", "W", "T", "Y", "U", "V", "X" };
            string[] str = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "m", "n", "l", "r", "p", "q", "w", "t", "y", "u", "v", "x" };
            string[] strNum = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

            if (n > 0)
            {
                Random rand = new Random(Guid.NewGuid().GetHashCode());
                int iRand;
                iRand = rand.Next(0, strCapital.Length - 1);
                strRandomPwd = strCapital[iRand];
                for (int i = 0; i < 2; i++)
                {
                    iRand = rand.Next(0, str.Length - 1);
                    strRandomPwd += str[iRand];
                }
                for (int i = 0; i < 3; i++)
                {
                    iRand = rand.Next(0, strNum.Length - 1);
                    strRandomPwd += strNum[iRand];
                }
            }
            return strRandomPwd;
        }

        /// <summary>
        /// 生成邀请码
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static string GetRandomCode(int n)
        {
            string code = string.Empty;
            string[] strCapital = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "L", "R", "P", "Q", "W", "T", "Y", "U", "V", "X", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
            if (n > 0)
            {
                Random rand = new Random(Guid.NewGuid().GetHashCode());
                for (int i = 0; i < n; i++)
                {
                    int irand = rand.Next(0, strCapital.Length - 1);
                    code += strCapital[irand];
                }

            }
            return code;
        }

        #region Cookie Helper
        /// <summary>
        /// 获取Cookie
        /// </summary>
        /// <param name="Name">Cookie名称</param>
        /// <returns></returns>
        public static string GetCookie(string Name)
        {
            string s = "";
            try
            {
                s = System.Web.HttpContext.Current.Request.Cookies.Get(Name).Value;
            }
            catch (Exception ex)
            {
            }
            return s;
        }
        /// <summary>
        /// 写Cookie
        /// </summary>
        /// <param name="Name">名称</param>
        /// <param name="Value">值</param>
        /// <param name="Path">路径</param>
        /// <param name="Domain">域</param>
        /// <param name="EndTime">失效日期</param>
        public static void SetCookie(string Name, string Value, string Path, string Domain, DateTime? EndTime)
        {
            try
            {
                System.Web.HttpCookie c = new HttpCookie(Name, Value);
                c.Path = Path;
                c.Domain = Domain;

                if (EndTime.HasValue)
                {
                    c.Expires = EndTime.Value;
                }
                System.Web.HttpContext.Current.Response.Cookies.Add(c);
            }
            catch (Exception ex)
            {
            }
        }
        #endregion

        #region 数据递归
        /// <summary>
        /// 数据递归排序(应用于checkbox)
        /// </summary>
        public static DataTable GetCheckBoxItems(DataTable dt, DataTable dtResult, string eleAttrName, string name, string id, string strParentID, string addStr)
        {
            string strFilter = null;
            if (strParentID != null && strParentID.Length > 0)
                strFilter = "ParentID = {0}";
            else
                strFilter = "ParentID is null";
            strFilter = string.Format(strFilter, strParentID);

            //开始递归排序
            DataRow[] drs = dt.Select(strFilter);
            foreach (DataRow dr in drs)
            {
                DataRow drNew = dtResult.NewRow();
                for (int i = 0; i < dr.Table.Columns.Count; i++)
                {
                    drNew[i] = dr[i];
                }
                drNew[name] = addStr + "<input type=\"checkbox\" name=\"" + eleAttrName + "\" value=\"" + drNew[id] + "\" />" + drNew[name];
                dtResult.Rows.Add(drNew);
                GetCheckBoxItems(dt, dtResult, eleAttrName, name, id, dr[id].ToString(), addStr + "\u3000");
            }

            return dtResult;
        }

        /// <summary>
        /// 数据递归排序(应用于droplist)
        /// </summary>
        public static DataTable GetDropItems(DataTable dt, DataTable dtResult, string name, string id, string strParentID, string addStr, string parentIDName = "ParentID")
        {
            string strFilter = null;
            if (strParentID != null && strParentID.Length > 0)
                strFilter = parentIDName + " = {0}";
            else
                strFilter = parentIDName + " is null";
            strFilter = string.Format(strFilter, strParentID);

            //开始递归排序
            DataRow[] drs = dt.Select(strFilter);
            foreach (DataRow dr in drs)
            {
                DataRow drNew = dtResult.NewRow();
                for (int i = 0; i < dr.Table.Columns.Count; i++)
                {
                    drNew[i] = dr[i];
                }
                drNew[name] = addStr + drNew[name];
                dtResult.Rows.Add(drNew);
                GetDropItems(dt, dtResult, name, id, dr[id].ToString(), addStr + "\u3000", parentIDName);
            }

            return dtResult;
        }

        #endregion

        #region 签名&加密

        /// <summary>
        /// 创建签名
        /// </summary>
        /// <param name="ht"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string CreateSign(Hashtable ht, string key)
        {
            StringBuilder strbuilder = new StringBuilder();
            ArrayList arrayList = new ArrayList(ht.Keys);
            arrayList.Sort();
            foreach (string k in arrayList)
            {
                string v = ht[k]?.ToString();
                //if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k.ToLower()) != 0 && "key".CompareTo(k.ToLower()) != 0)
                if ("sign".CompareTo(k.ToLower()) != 0 && "key".CompareTo(k.ToLower()) != 0)
                    strbuilder.Append(k.ToLower() + "=" + v + "&");
            }
            strbuilder.Append("key=" + key);
            string sign = Md5Encrypt(strbuilder.ToString(), Encoding.UTF8).ToLower();
            return sign;
        }

        /// <summary>
        /// 检查签名
        /// </summary>
        /// <returns></returns>
        public static bool CheckSign(Hashtable ht, string key)
        {
            string sign = CreateSign(ht, key);
            return GetHashTabValue(ht, "sign").ToLower().Equals(sign);
        }

        /// <summary>
        /// 获取hashtable值
        /// </summary>
        public static string GetHashTabValue(Hashtable hat, string name)
        {
            string s = (string)hat[name];
            return (null == s) ? "" : s;
        }

        /// <summary>
        /// 将字符串经过md5加密，返回加密后的字符串的小写表示
        /// </summary>
        public static string Md5Encrypt(string strToBeEncrypt, Encoding encoding)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            Byte[] FromData = encoding.GetBytes(strToBeEncrypt);
            Byte[] TargetData = md5.ComputeHash(FromData);
            string Byte2String = "";
            for (int i = 0; i < TargetData.Length; i++)
            {
                Byte2String += TargetData[i].ToString("x2");
            }
            return Byte2String.ToLower();
        }

        /// <summary>
        /// 	Encodes the input value to a Base64 string using the default encoding.
        /// </summary>
        /// <param name = "value">The input value.</param>
        /// <returns>The Base 64 encoded string</returns>
        public static string EncodeBase64(string value)
        {
            return EncodeBase64(value, null);
        }

        /// <summary>
        /// 	Encodes the input value to a Base64 string using the supplied encoding.
        /// </summary>
        /// <param name = "value">The input value.</param>
        /// <param name = "encoding">The encoding.</param>
        /// <returns>The Base 64 encoded string</returns>
        public static string EncodeBase64(string value, Encoding encoding)
        {
            encoding = (encoding ?? Encoding.UTF8);
            var bytes = encoding.GetBytes(value);
            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// 	Decodes a Base 64 encoded value to a string using the default encoding.
        /// </summary>
        /// <param name = "encodedValue">The Base 64 encoded value.</param>
        /// <returns>The decoded string</returns>
        public static string DecodeBase64(string encodedValue)
        {
            encodedValue = encodedValue.Replace("\n", "").Replace(" ", "+");
            encodedValue = Regex.Unescape(encodedValue);
            return DecodeBase64(encodedValue, null);
        }

        /// <summary>
        /// 	Decodes a Base 64 encoded value to a string using the supplied encoding.
        /// </summary>
        /// <param name = "encodedValue">The Base 64 encoded value.</param>
        /// <param name = "encoding">The encoding.</param>
        /// <returns>The decoded string</returns>
        public static string DecodeBase64(string encodedValue, Encoding encoding)
        {
            encoding = (encoding ?? Encoding.UTF8);
            var bytes = Convert.FromBase64String(encodedValue);
            return encoding.GetString(bytes);
        }

        public static string ConvertToBase64Str(string str)
        {
            str = Regex.Unescape(str);
            return str.Replace("\r", "")
                            .Replace("\n", "")
                            .Replace(" ", "+");
        }

        #endregion 签名&加密

        /// <summary>
        /// 检查时间戳是否有效
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <param name="timeValid">有效时间 单位：秒</param>
        /// <returns></returns>
        public static bool CheckTimeStamp(int timeStamp, int timeValid)
        {
            int nowTimeStamp = GetTimeStamp();
            if (Math.Abs(nowTimeStamp - timeStamp) > timeValid)
                return false;
            return true;
        }

        /// <summary>
        /// 获取Unix时间戳
        /// </summary>
        /// <returns></returns>
        public static int GetTimeStamp()
        {
            return ConvertTimeInt(DateTime.Now);
        }

        /// <summary>
        /// 返回标准时间格式string
        /// </summary>
        public static string GetDateTime()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式
        /// </summary>
        /// <param name=”time”></param>
        /// <returns></returns>
        public static int ConvertTimeInt(System.DateTime time)
        {
            //System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            DateTime startTime = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1, 8, 0, 0), TimeZoneInfo.Local);
            return (int)(time - startTime).TotalSeconds;
        }

        /// <summary>
        /// 检查是否重复提交
        /// </summary>
        /// <returns></returns>
        public static bool CheckDoubleSubmit(string sign)
        {
            try
            {
                string key = "apisubmitsign." + sign;
                string signData = RedisService.Get<string>(key);
                if (!string.IsNullOrEmpty(signData))
                {
                    return false;
                }
                else
                {
                    DateTime dt1 = DateTime.Now;
                    DateTime dt2 = DateTime.Now.AddMinutes(30);
                    TimeSpan ts = dt2.Subtract(dt1);
                    RedisService.Set(key, GetDateTime(), ts);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("检查是否重复提交" + ex.Message);
            }
            return true;
        }

        /// <summary>
        /// 分割字符串
        /// </summary>
        public static string[] GetStrings(string str, string strspilt)
        {
            return str.Split(new string[] { strspilt }, StringSplitOptions.RemoveEmptyEntries);
        }

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetClientIP()
        {
            string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (null == result || result == String.Empty)
            {
                result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }


            if (null == result || result == String.Empty)
            {
                result = HttpContext.Current.Request.UserHostAddress;
            }
            return result;
        }

        /// <summary>
        /// 生成订单号(默认16位)
        /// digit 订单号位数（除去前缀）
        /// </summary>
        /// <returns></returns>
        public static string BuildOrderId(string str = "", int digit = 16)
        {
            StringBuilder builder = new StringBuilder();
            string strTm = DateTime.Now.ToString("yyMMddHHmmss");

            string strRm = string.Empty;
            if (digit >= 12)
            {
                //生成随机数
                Random rand = new Random(Guid.NewGuid().GetHashCode());
                for (int i = 0; i < digit - 12; i++)
                {
                    strRm += rand.Next(0, 9).ToString();
                }
            }
            return builder.Append(str).Append(strTm).Append(strRm).ToString();
        }

        /// <summary>
        /// 将s的属性值传给D
        /// </summary>
        /// <typeparam name="D"></typeparam>
        /// <typeparam name="S"></typeparam>
        /// <param name="s"></param>
        /// <returns></returns>
        public static D Mapper<D, S>(S s)
        {
            D d = Activator.CreateInstance<D>();
            try
            {
                var Types = s.GetType();//获得类型
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段
                {
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {
                        if (dp.Name == sp.Name)//判断属性名是否相同
                        {
                            dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return d;
        }
        public static void Mapper<D, S>(D d, S s, IList<string> exceptList, bool exceptNull = true)
        {
            try
            {
                var Types = s.GetType();//获得类型
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段
                {
                    if (exceptList.Contains(sp.Name))
                        continue;
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {
                        if (exceptList.Contains(dp.Name))
                            continue;
                        if (dp.Name == sp.Name)//判断属性名是否相同
                        {
                            object objValue = sp.GetValue(s, null);
                            if (exceptNull)
                            {
                                if (objValue != null)
                                    dp.SetValue(d, objValue, null);
                            }
                            else
                            {
                                dp.SetValue(d, objValue, null);//获得s对象属性的值复制给d对象的属性
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 去除对象里字符串类型参数的前后空格
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public static void Trim<T>(T obj)
        {
            try
            {
                var Types = obj.GetType();//获得类型
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段
                {
                    if (sp.PropertyType == typeof(string))
                    {
                        object objValue = sp.GetValue(obj, null);
                        if (objValue != null)
                        {
                            sp.SetValue(obj, objValue.ToString().Trim(), null);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("参数去空格失败" + JsonHelper.Serialize(obj) + ex.GetExcetionMessage());
            }
        }

    }
}
